package org.softmed.rest.generation.solution;

import java.io.File;
import java.util.List;

import org.softmed.filehandling.FileUtil;
import org.softmed.persistence.PersistenceManager;
import org.softmed.persistence.PersistenceManagerProvider;
import org.softmed.persistence.PersistenceProvider;
import org.softmed.rest.config.Application;
import org.softmed.rest.generation.GenerationData;
import org.softmed.rest.generation.ServiceGenerationProcessor;
import org.softmed.rest.generation.refactoring.stored.StoredDataCreator;
import org.softmed.rest.generation.scafold.AppConfig;
import org.softmed.rest.generation.scafold.ModConfig;
import org.softmed.rest.server.core.restlet.RESTServer;
import org.softmed.rest.server.core.restlet.ResourceSetup;

import com.google.inject.Inject;
import com.google.inject.name.Named;

public class SolutionBuilder {

	FileUtil util = new FileUtil();

	@Inject
	PersistenceFactory persistenceFactory;

	@Inject
	@Named("RESTAdminProviderName")
	String RESTAdminProviderName;

	@Inject
	@Named("StoredRESTContextName")
	String storedRESTContextName;

	@Inject
	@Named("DefaultXMLSuiteName")
	String defaultXMLSuite;

	@Inject
	RESTServer server;

	String fileName = "refactor.odb";

	ServiceGenerationProcessor serviceGenerationProcessor = new ServiceGenerationProcessor();

	@Inject
	RefactorProcessor refactorProcessor;

	StoredDataCreator storedDataCreator = new StoredDataCreator();

	public void processAppConfigurations(List<AppConfig> apps) throws Throwable {

//		RESTletServerApplication sap = server.getApplication();
//		sap.removeAllResources();
		server.removeAllResources();

		for (AppConfig app : apps) {
			try {
				processConfig(app);
			} catch (Throwable t) {
				t.printStackTrace();
			}
		}

	}

	private void processConfig(AppConfig app) throws Throwable {
		// only generate if there is any class registered
		if (app.isGenerateService() && app.getClasses() != null
				&& app.getClasses().size() > 0) {

			Application application = null;
			GenerationData genData = serviceGenerationProcessor.buildApp(app,
					defaultXMLSuite);
			app.setGenerationData(genData);

			// TODO need to use classURIBuilder to create association from
			// classes
			// to URIS even if not generated !!!

			if (app.isStoreREST()) {
				// check if there is anything stored at all yet
				if (app.isRefactor()) {
					if (isAlreadyStored(app))
						refactor(app); // and store changes
					else
						storeServiceData(app);
					// else
					// //what if its not supposed to refactor ?
					// //then generating stuff is useless !!!
				} else
					storeServiceData(app);

				// storeRefactorData(app);

				// app.setRestContext(storedRESTContextName);
			} else if (app.getRestContext() != null
					&& app.getRestContext().length() > 0) {
				// deploy to context
				// RESTletServerApplication sap = server.getApplication();

				ResourceSetup resourceSetup = new ResourceSetup();
				resourceSetup.setServer(server);
				resourceSetup.setContextName(app.getRestContext());
				resourceSetup
						.setupApp(app.getGenerationData().getApplication());
			}

		}

		if (isAlreadyStored(app)) {
			// TODO build the URI's all the same
		}

	}

	private void storeServiceData(AppConfig app) throws Throwable {
		// this is deactivated until the refactor system is done
		if (true)
			return;

		PersistenceProvider pp = PersistenceManagerProvider.getProviders().get(
				RESTAdminProviderName);
		PersistenceManager pm = pp.getPersistenceManager();
		pm.connect();
		pm.save(app.getGenerationData().getApplication());
		pm.commit();
		pm.close();

	}

	private boolean isAlreadyStored(AppConfig app) {
		// TODO this isn't implemented yet, so forget it!!!
		if (true)
			return false;
		// check if there is anything stored at all yet
		File file = new File(getFilePath(app.getPath()));
		if (file.exists())
			return true;

		List<ModConfig> mods = app.getModules();
		for (ModConfig modConfig : mods) {
			file = new File(getFilePath(modConfig.getPath()));
			if (file.exists())
				return true;
		}

		return false;
	}

//	private void storeRefactorData(AppConfig app) {
//
//		ApplicationService service = app.getGenerationData()
//				.getApplicationService();
//
//		ApplicationServiceData data = storedDataCreator.getStoredData(service);
//
//		storeData(data, app.getPath());
//
//		List<ModConfig> mods = app.getModules();
//		for (ModConfig modConfig : mods) {
//			ModuleService moduleService = modConfig.getModuleService();
//			ModuleServiceData modData = storedDataCreator
//					.getStoredData(moduleService);
//			storeData(modData, modConfig.getPath());
//		}
//
//	}

//	protected void storeData(Object data, String path) {
//		File file = new File(getFilePath(path));
//		if (file.exists())
//			file.delete();
//
//		ODB odb = ODBFactory.open(getFilePath(path));
//		odb.store(data);
//		odb.close();
//	}

	protected String getFilePath(String path) {
		return path + "/" + fileName;
	}

	private void refactor(AppConfig app) {
		refactorProcessor.refactor(app);
	}

	public boolean persistenceProviderChanged(List<AppConfig> apps)
			throws Throwable {
		boolean changed = false;
		for (AppConfig app : apps) {

			// if there are no registered classes to persist, don't create
			// a persistence provider
			if (app.getClasses() == null || app.getClasses().size() == 0)
				continue;

			if (hasNoPersistenceSolution(app)) {
				persistenceFactory.createPersistenceSolution(app);
				changed = true;
			}

		}
		return changed;

	}

	private boolean hasNoPersistenceSolution(AppConfig app) {
		if (app.isPersistenceDefinitionFileExists())
			return false;

		String provider = app.getPersistenceProvider();
		if (provider == null || provider.length() == 0) {
			List<ModConfig> mods = app.getModules();
			for (ModConfig mod : mods) {
				provider = mod.getPersistenceProvider();
				if (provider != null && provider.length() > 0)
					return false;
			}
			return true;
		} else
			return false;

	}

	public PersistenceFactory getPersistenceFactory() {
		return persistenceFactory;
	}

	public void setPersistenceFactory(PersistenceFactory persistenceFactory) {
		this.persistenceFactory = persistenceFactory;
	}

	public String getStoredRESTContextName() {
		return storedRESTContextName;
	}

	public void setStoredRESTContextName(String storedRESTContextName) {
		this.storedRESTContextName = storedRESTContextName;
	}

	public String getDefaultXMLSuite() {
		return defaultXMLSuite;
	}

	public void setDefaultXMLSuite(String defaultXMLSuite) {
		this.defaultXMLSuite = defaultXMLSuite;
	}

	public RefactorProcessor getRefactorProcessor() {
		return refactorProcessor;
	}

	public void setRefactorProcessor(RefactorProcessor refactorProcessor) {
		this.refactorProcessor = refactorProcessor;
	}

}
